﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TorchView.Game;
using System.Collections.Specialized;
using TorchView.SharedStashEditor.Helpers;
using TorchView.Windows;
using System.Windows.Input;
using Microsoft.Practices.Unity;
using System.Windows;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace TorchView.SharedStashEditor.ViewModels
{
    public class ItemViewModel : INotifyPropertyChanged
    {
        const string ITEM_NAME_TAG = "[ITEM]";

        private IUnityContainer _Container;

        private Item _item;
        private bool _modified = false;

        private long _ItemModelID;
        private string _Name;
        private string _Prefix;
        private string _Suffix;
        private uint _TimesHeirloomed;
        private uint _TimesEnchanted;
        private uint _Stack;
        private int _TotalSockets;
        private int _MaxDamage;
        private int _Armor;

        private EffectListViewModel PassiveEffectsVM;
        private EffectListViewModel UseEffectsVM;
        private EffectListViewModel TargetEffectsVM;

        public ItemViewModel()
        {
            _item = new Item();
            Load();
        }

        public ItemViewModel(Item item)
        {
            _item = item;
            Load();
        }

        private void Load()
        {
            _Container = SharedStashEditorPlugin.Container;

            _ItemModelID = _item.ItemModelID;
            _Name = _item.Name;
            _Prefix = _item.Prefix;
            _Suffix = _item.Suffix;
            _TimesHeirloomed = _item.TimesHeirloomed;
            _TimesEnchanted = _item.TimesEnchanted;
            _Stack = _item.Stack;
            _TotalSockets = _item.TotalSockets;
            _MaxDamage = _item.MaxDamage;
            _Armor = _item.Armor;

            BonusDamage = new ObservableCollection2<DamageBonus>();
            foreach (DamageBonus bonus in _item.BonusDamage)
            {
                BonusDamage.Add(new DamageBonus(bonus));
            }
            BonusDamage.CollectionChanged += new NotifyCollectionChangedEventHandler(CollectionChanged);

            PassiveEffectsVM = new EffectListViewModel(EffectActivationType.Passive, this, _item.PassiveEffects);
            UseEffectsVM = new EffectListViewModel(EffectActivationType.Use, this, _item.UseEffects);
            TargetEffectsVM = new EffectListViewModel(EffectActivationType.Target, this, _item.TargetEffects);

            EffectLists = new ObservableCollection<EffectListViewModel>();
            EffectLists.Add(PassiveEffectsVM);
            EffectLists.Add(UseEffectsVM);
            EffectLists.Add(TargetEffectsVM);

            _AddAffixCommand = new DirectCommand(ExecuteAddAffixCommand);

            _AddDamageBonusCommand = new DirectCommand(ExecuteAddDamageCommand);
            _EditDamageBonusCommand = new DirectCommand(ExecuteEditDamageCommand);
            _RemoveDamageBonusCommand = new DirectCommand(ExecuteRemoveDamageCommand);
        }

        private void CollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
        {
            _modified = true;
        }


        public void Save()
        {
            if (_modified)
            {
                _item.ItemModelID = _ItemModelID;
                _item.Name = _Name;
                _item.TimesHeirloomed = _TimesHeirloomed;
                _item.TimesEnchanted = _TimesEnchanted;
                _item.Stack = _Stack;
                _item.TotalSockets = _TotalSockets;
                _item.MaxDamage = _MaxDamage;
                _item.Armor = _Armor;

                _item.BonusDamage = BonusDamage.ToArray<DamageBonus>();
                if (PassiveEffectsVM.Modified)
                {
                    _item.PassiveEffects = PassiveEffectsVM.EffectList.ToArray<Effect>();
                    PassiveEffectsVM.Modified = false;
                }

                if (UseEffectsVM.Modified)
                {
                    _item.UseEffects = UseEffectsVM.EffectList.ToArray<Effect>();
                    UseEffectsVM.Modified = false;
                }
                if (TargetEffectsVM.Modified)
                {
                    _item.TargetEffects = TargetEffectsVM.EffectList.ToArray<Effect>();
                    TargetEffectsVM.Modified = false;
                }

                _modified = false;
            }
        }


        public void AttachEffect(TorchView.GameContent.Units.Effect effect)
        {
            Effect gameEffect = effect.CreateGameEffect();
            switch (gameEffect.EffectType)
            {
                case EffectActivationType.Passive:
                    PassiveEffectsVM.Add(gameEffect);
                    break;
                case EffectActivationType.Target:
                    TargetEffectsVM.Add(gameEffect);
                    break;
                case EffectActivationType.Use:
                    UseEffectsVM.Add(gameEffect);
                    break;
            }
        }


        private void ExecuteAddAffixCommand(object parameter)
        {
            var viewModel = _Container.Resolve<IAddAffixViewModel>(new PropertyOverride("Owner", Application.Current.MainWindow));

            viewModel.Init(this);
            if (viewModel.View.ShowDialog() ?? false)
            {
                if (viewModel.SelectedAffix != null)
                {
                    //Copy Prefix and Suffix
                    if (_Suffix.Length == 0 && viewModel.SelectedAffix.Suffix.Length > 0)
                    {
                        Suffix = String.Copy(viewModel.SelectedAffix.Suffix);
                    }
                    if (_Prefix.Length == 0 && viewModel.SelectedAffix.Prefix.Length > 0)
                    {
                        Prefix = String.Copy(viewModel.SelectedAffix.Prefix);
                    }

                    foreach (GameContent.Units.Effect affixEffect in viewModel.SelectedAffix.Effects)
                    {
                        AttachEffect(affixEffect);
                    }
                }
            }
        }

        private void ExecuteAddDamageCommand(object parameter)
        {
            var viewModel = _Container.Resolve<IEditDamageBonusViewModel>(new PropertyOverride("Owner", Application.Current.MainWindow));
            viewModel.Mode = EditMode.Add;
            viewModel.Damage = new DamageBonus();
            if (viewModel.View.ShowDialog() ?? false)
            {
                BonusDamage.Add(viewModel.Damage);
            }
        }

        private void ExecuteEditDamageCommand(object parameter)
        {
            if (SelectedDamage != null)
            {
                var viewModel = _Container.Resolve<IEditDamageBonusViewModel>(new PropertyOverride("Owner", Application.Current.MainWindow));
                viewModel.Mode = EditMode.Edit;
                viewModel.Damage = new DamageBonus();
                viewModel.Damage.Damage = SelectedDamage.Damage;
                viewModel.Damage.Type = SelectedDamage.Type;

                if (viewModel.View.ShowDialog() ?? false)
                {
                    SelectedDamage.Damage = viewModel.Damage.Damage;
                    SelectedDamage.Type = viewModel.Damage.Type;
                    BonusDamage.Refresh();
                    _modified = true;
                }
            }
        }

        private void ExecuteRemoveDamageCommand(object parameter)
        {
            if (SelectedDamage != null)
            {
                if (_Container.Resolve<IMessageBoxService>().Show(Application.Current.MainWindow, string.Format("Are you sure you want to damage bonus[{0}]?", SelectedDamage), "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No) == MessageBoxResult.Yes)
                {
                    BonusDamage.Remove(SelectedDamage);
                }
            }
        }

        #region Commands
        private DirectCommand _AddDamageBonusCommand;
        public ICommand AddDamageBonusCommand { get { return _AddDamageBonusCommand; } }

        private DirectCommand _EditDamageBonusCommand;
        public ICommand EditDamageBonusCommand { get { return _EditDamageBonusCommand; } }

        private DirectCommand _RemoveDamageBonusCommand;
        public ICommand RemoveDamageBonusCommand { get { return _RemoveDamageBonusCommand; } }

        private DirectCommand _AddAffixCommand;
        public ICommand AddAffixCommand { get { return _AddAffixCommand; } }
        #endregion

        public override string ToString()
        {
            string itemName = _Name;
            if(_Prefix.Length > 0)
                itemName = _Prefix.Replace(ITEM_NAME_TAG, itemName);

            if(_Suffix.Length > 0)
                itemName = _Suffix.Replace(ITEM_NAME_TAG, itemName);
            return itemName;
        }

        #region Properties

        //For Selection
        public DamageBonus SelectedDamage { get; set; }
        public int SelectedEffectList { get { return 0; } }

        public ObservableCollection2<DamageBonus> BonusDamage { get; private set; }
        public ObservableCollection<EffectListViewModel> EffectLists { get; private set; }

        public bool Modified 
        { 
            get { return _modified; }
            set { _modified = value; }
        }

        public Item InnerItem { get { return _item; } }
        public long ItemModelID
        {
            get { return _ItemModelID; }
            set
            {
                if (_ItemModelID != value)
                {
                    _ItemModelID = value;
                    _modified = true;
                    NotifyPropertyChanged("ItemModelID");
                }
            }
        }
        public string Name
        {
            get { return _Name; }
            set
            {
                if (_Name != value)
                {
                    _Name = value;
                    _modified = true;
                    NotifyPropertyChanged("Name");
                }
            }
        }
        public string Prefix
        {
            get { return _Prefix; }
            set
            {
                if (_Prefix != value)
                {
                    _Prefix = value;
                    _modified = true;
                    NotifyPropertyChanged("Prefix");
                }
            }
        }
        public string Suffix
        {
            get { return _Suffix; }
            set
            {
                if (_Suffix != value)
                {
                    _Suffix = value;
                    _modified = true;
                    NotifyPropertyChanged("Suffix");
                }
            }
        }
        public uint TimesHeirloomed
        {
            get { return _TimesHeirloomed; } 
            set {
                if (_TimesHeirloomed != value)
                {
                    _TimesHeirloomed = value;
                    _modified = true;
                    NotifyPropertyChanged("TimesHeirloomed");
                }
            } 
        }
        public uint TimesEnchanted
        {
            get { return _TimesEnchanted; } 
            set 
            {
                if (_TimesEnchanted != value)
                {
                    _TimesEnchanted = value;
                    _modified = true;
                    NotifyPropertyChanged("TimesEnchanted");
                }
            }
        }
        public uint Stack
        {
            get { return _Stack; }
            set 
            {
                if (_Stack != value)
                {
                    _Stack = value;
                    _modified = true;
                    NotifyPropertyChanged("Stack");
                }
            }
        }
        public int TotalSockets 
        { 
            get { return _TotalSockets; }
            set 
            {
                if (_TotalSockets != value)
                {
                    _TotalSockets = value;
                    _modified = true;
                    NotifyPropertyChanged("TotalSockets");
                }
            } 
        }
        public int MaxDamage 
        {
            get { return _MaxDamage; }
            set 
            {
                if (_MaxDamage != value)
                {
                    _MaxDamage = value;
                    _modified = true;
                    NotifyPropertyChanged("MaxDamage");
                }
            }
        }
        public int Armor 
        { 
            get { return _Armor; }
            set 
            {
                if (_Armor != value)
                {
                    _Armor = value;
                    _modified = true;
                    NotifyPropertyChanged("Armor");
                }
            }
        }
        
        #endregion

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}
